import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from Ui_MainWindow import MainWindow
import socket



class HostIP(object):
    def __init__(self):
        self.ip = ''
        self.get_host_ip()

    def get_host_ip(self):
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        try:
            s.connect(('8.8.8.8', 80))
            self.ip = s.getsockname()[0]
        except IOError:
            print("socket error!")
        finally:
            s.close()

class Window:
    def __init__(self):
        self.ui = MainWindow()
        self.localhost_ip = ''
        self.socket = None
        self.threadRecv = None
        self.initUi()

    def initUi(self):
        self.localhost_ip = HostIP().ip
        self.ui.line_local.setText(self.localhost_ip)
        # self.ui.line_local.setEnabled(False)
        self.ui.line_lport.setText("8080")
        self.ui.btn_connect.clicked.connect(self.connect)
        self.ui.btn_send.clicked.connect(self.send_data)
        self.ui.btn_clearsend.clicked.connect(self.clear_send)
        self.ui.btn_clearrecv.clicked.connect(self.clear_recv)

        self.test()

    def test(self):
        self.ui.line_dhost.setText("192.168.0.115")
        self.ui.line_dport.setText("8800")

    def check(self):
        protocol = self.ui.comboBox_protocol.currentText()
        flag = 0
        if protocol == 'UDP':
            self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            flag = 0
        elif protocol == 'TCP Server':
            self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            flag = 1

        elif protocol == 'TCP Client':
            self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            flag = 2

        self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        return flag

    def connect(self):
        if self.ui.status == 1:
            self.ui.flag = self.check()
            lport = eval(self.ui.line_lport.text())
            if self.ui.flag == 0:
                self.socket.bind(("", lport))
                self.threadRecv = ThreadRecv(self.socket, self.ui)
                self.threadRecv.sig.connect(self.recv_data)
                self.threadRecv.start()
                self.ui.text_datarecv.append("打开成功")

            elif self.ui.flag == 1:
                self.socket.bind(("", lport))
                self.socket.listen(5)

            elif self.ui.flag == 2:
                dhost = self.ui.line_dhost.text()
                dport = eval(self.ui.line_dport.text())
                addr = (dhost, dport)
                self.socket.connect(addr)
                self.threadRecv = ThreadRecv(self.socket, self.ui)
                self.threadRecv.sig.connect(self.recv_data)
                # print(self.socket)
                self.threadRecv.start()
                self.ui.text_datarecv.append("连接成功")

        else:
            if self.ui.flag == 0:
                pass
            if self.ui.flag == 2:
                self.socket.shutdown(2)

            self.socket.close()
            self.threadRecv.quit()
            self.socket = None


            # self.threadRecv.wait()
            self.ui.text_datarecv.append("关闭成功")



    def recv_data(self, info):
        if self.ui.status == 0:
            return

        if self.ui.flag == 0:
            info = eval(info)
            addr = str(info[0])
            data = info[1]
            self.ui.text_datarecv.append(addr+">>"+data)
        if self.ui.flag == 2:
            self.ui.text_datarecv.append("server>>"+info)


    def send_data(self):
        if self.ui.status == 0:
            return
        if not self.socket:
            return

        data = self.ui.text_datasend.toPlainText()
        if data == '':
            return
        dhost = self.ui.line_dhost.text()
        dport = eval(self.ui.line_dport.text())
        addr = (dhost, dport)
        if self.ui.flag == 0:
            self.socket.sendto(data.encode('gb2312'), addr)
        if self.ui.flag == 1:
            pass
        if self.ui.flag == 2:
            self.socket.send(data.encode('gb2312'))

        self.ui.text_datasend.clear()
        self.ui.text_datarecv.append("{}<<[{}:{}]".format(data, dhost, dport))

    def clear(self, area):
        area.clear()

    def clear_recv(self):
        self.clear(self.ui.text_datarecv)

    def clear_send(self):
        self.clear(self.ui.text_datasend)



class ThreadRecv(QThread):
    sig = pyqtSignal(str)
    def __init__(self, socket, ui):
        super(ThreadRecv, self).__init__()
        self.socket = socket
        self.ui = ui
    def run(self):
        # print("status: {}".format(self.ui.status))
        # print("flag: {}".format(self.ui.flag))
        while True:
            if self.ui.status == 0:
                break
            if self.ui.flag == 0:
                rec_info = self.socket.recvfrom(1024)
                addr = str(rec_info[1])
                data = rec_info[0].decode("gb2312")
                info = str([addr, data])
                self.sig.emit(info)
            if self.ui.flag == 2:
                rec_info = self.socket.recv(1024)
                info = str(rec_info.decode("gb2312"))
                self.sig.emit(info)




if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = Window()
    window.ui.show()
    sys.exit(app.exec_())

